package com.kinsin.kinsinutil

import kotlin.math.roundToLong
import java.util.Locale

/**
 * 存储单位转换工具类
 * @author kinsin
 */
object StorageUnitUtils {

    // region 常量定义
    private const val BYTES_IN_KB = 1024.0
    private const val BYTES_IN_MB = 1024.0 * 1024.0
    private const val BYTES_IN_GB = 1024.0 * 1024.0 * 1024.0
    private const val BYTES_IN_TB = 1024.0 * 1024.0 * 1024.0 * 1024.0
    private const val BYTES_IN_PB = 1024.0 * 1024.0 * 1024.0 * 1024.0 * 1024.0
    private const val BYTES_IN_EB = 1024.0 * 1024.0 * 1024.0 * 1024.0 * 1024.0 * 1024.0
    // endregion

    // region 正向转换（字节 -> 其他单位）
    fun bytesToKB(bytes: Long): Double = bytes.toDouble() / BYTES_IN_KB
    fun bytesToMB(bytes: Long): Double = bytes.toDouble() / BYTES_IN_MB
    fun bytesToGB(bytes: Long): Double = bytes.toDouble() / BYTES_IN_GB
    fun bytesToTB(bytes: Long): Double = bytes.toDouble() / BYTES_IN_TB
    fun bytesToPB(bytes: Long): Double = bytes.toDouble() / BYTES_IN_PB
    fun bytesToEB(bytes: Long): Double = bytes.toDouble() / BYTES_IN_EB

    /**
     * 智能转换字节为最适合的人类可读格式
     * @throws IllegalArgumentException 当输入负值时抛出
     */
    fun bytesToHumanReadable(bytes: Long): String {
        require(bytes >= 0) { "Byte size cannot be negative" }

        return when {
            bytes < BYTES_IN_KB -> "$bytes B"
            bytes < BYTES_IN_MB -> "%.2f KB".format(Locale.ENGLISH, bytesToKB(bytes))
            bytes < BYTES_IN_GB -> "%.2f MB".format(Locale.ENGLISH, bytesToMB(bytes))
            bytes < BYTES_IN_TB -> "%.2f GB".format(Locale.ENGLISH, bytesToGB(bytes))
            bytes < BYTES_IN_PB -> "%.2f TB".format(Locale.ENGLISH, bytesToTB(bytes))
            bytes < BYTES_IN_EB -> "%.2f PB".format(Locale.ENGLISH, bytesToPB(bytes))
            else -> "%.2f EB".format(Locale.ENGLISH, bytesToEB(bytes))
        }
    }
    // endregion

    // region 反向转换（其他单位 -> 字节）
    /**
     * 带安全校验的单位转换，避免溢出和精度丢失
     * @throws ArithmeticException 当计算结果超过Long最大值时抛出
     */
    fun kbToBytes(kb: Double): Long = convertToBytes(kb, BYTES_IN_KB)
    fun mbToBytes(mb: Double): Long = convertToBytes(mb, BYTES_IN_MB)
    fun gbToBytes(gb: Double): Long = convertToBytes(gb, BYTES_IN_GB)
    fun tbToBytes(tb: Double): Long = convertToBytes(tb, BYTES_IN_TB)
    fun pbToBytes(pb: Double): Long = convertToBytes(pb, BYTES_IN_PB)
    fun ebToBytes(eb: Double): Long = convertToBytes(eb, BYTES_IN_EB)

    private fun convertToBytes(value: Double, multiplier: Double): Long {
        val bytes = value * multiplier
        require(!bytes.isNaN()) { "Invalid numerical value" }
        if (bytes > Long.MAX_VALUE) {
            throw ArithmeticException("Value $value exceeds Long.MAX_VALUE")
        }
        return bytes.roundToLong()
    }
    // endregion
}